home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 11: TSX-11 / Linux Cubed Series 11 - TSX-11 Vol 1.iso / sbin / bootutil.1 / bootutil / bootutils / mount / nfsmount.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-01  |  7.6 KB  |  335 lines

  1. /* nfsmount.c - simple nfs mount - rick sladkey */
  2.  
  3. #include <stdio.h>
  4. #include <rpc/rpc.h>
  5. #include <sys/socket.h>
  6. #include <sys/time.h>
  7. #include <string.h>
  8. #include <netdb.h>
  9. #include <arpa/inet.h>
  10. #include <errno.h>
  11.  
  12. #include "sundries.h"
  13.  
  14. #include "mount.h"
  15.  
  16. /* this is ugly, I'll fix the kernel header file so it doesn't conflict */
  17.  
  18. #define RPC_SUCCESS NFS_RPC_SUCCESS
  19. #define RPC_MISMATCH NFS_RPC_MISMATCH
  20. #include <linux/nfs.h>
  21. #undef RPC_SUCCESS
  22. #undef RPC_MISMATCH
  23.  
  24. #include <linux/nfs_mount.h>
  25.  
  26. static char *nfs_strerror(int stat);
  27.  
  28. int nfsmount(const char *spec, const char *node, int *flags,
  29.          char **orig_opts, char **extra_opts)
  30. {
  31.     char hostdir[1024];
  32.     CLIENT *mclient;
  33.     char *hostname;
  34.     char *dirname;
  35.     char new_opts[1024];
  36.     fhandle root_fhandle;
  37.     struct timeval total_timeout;
  38.     enum clnt_stat clnt_stat;
  39.     static struct nfs_mount_data data;
  40.     char *opts, *opt, *opteq;
  41.     int val;
  42.     struct hostent *hp;
  43.     struct sockaddr_in server_addr;
  44.     int msock, fsock;
  45.     struct timeval pertry_timeout;
  46.     struct fhstatus status;
  47.     char *s;
  48.     int port;
  49.     int bg;
  50.     int soft;
  51.     int intr;
  52.     int posix;
  53.     int nocto;
  54.     int noac;
  55.     int retry;
  56.  
  57.     msock = fsock = -1;
  58.     mclient = NULL;
  59.     strcpy(hostdir, spec);
  60.     if ((s = (strchr(hostdir, ':')))) {
  61.         hostname = hostdir;
  62.         dirname = s + 1;
  63.         *s = '\0';
  64.     }
  65.     else {
  66.         fprintf(stderr, "mount: "
  67.             "directory to mount not in host:dir format\n");
  68.         goto fail;
  69.     }
  70.  
  71.     if (hostname[0] >= '0' && hostname[0] <= '9') {
  72.         server_addr.sin_family = AF_INET;
  73.         server_addr.sin_addr.s_addr = inet_addr(hostname);
  74.     }
  75.     else if ((hp = gethostbyname(hostname)) == NULL) {
  76.         fprintf(stderr, "mount: can't get address for %s\n", hostname);
  77.         goto fail;
  78.     }
  79.     else {
  80.         server_addr.sin_family = AF_INET;
  81.         memcpy(&server_addr.sin_addr, hp->h_addr, hp->h_length);
  82.     }
  83.  
  84.     /* add IP address to mtab options for use when unmounting */
  85.  
  86.     sprintf(new_opts, "%s%saddr=%s",
  87.         *orig_opts ? *orig_opts : "",
  88.         *orig_opts ? "," : "",
  89.         inet_ntoa(server_addr.sin_addr));
  90.     *orig_opts = strdup(new_opts);
  91.  
  92.     /* set default options */
  93.  
  94.     data.rsize    = 0; /* let kernel decide */
  95.     data.wsize    = 0; /* let kernel decide */
  96.     data.timeo    = 7;
  97.     data.retrans    = 3;
  98.     data.acregmin    = 3;
  99.     data.acregmax    = 60;
  100.     data.acdirmin    = 30;
  101.     data.acdirmax    = 60;
  102.  
  103.     port = 2049;
  104.     bg = 0;
  105.     soft = 0;
  106.     intr = 0;
  107.     posix = 0;
  108.     nocto = 0;
  109.     noac = 0;
  110.     retry = 10000;
  111.  
  112.     /* parse options */
  113.  
  114.     if ((opts = *extra_opts)) {
  115.         for (opt = strtok(opts, ","); opt; opt = strtok(NULL, ",")) {
  116.             if ((opteq = strchr(opt, '='))) {
  117.                 val = atoi(opteq + 1);    
  118.                 *opteq = '\0';
  119.                 if (!strcmp(opt, "rsize"))
  120.                     data.rsize = val;
  121.                 else if (!strcmp(opt, "wsize"))
  122.                     data.wsize = val;
  123.                 else if (!strcmp(opt, "timeo"))
  124.                     data.timeo = val;
  125.                 else if (!strcmp(opt, "retrans"))
  126.                     data.retrans = val;
  127.                 else if (!strcmp(opt, "acregmin"))
  128.                     data.acregmin = val;
  129.                 else if (!strcmp(opt, "acregmax"))
  130.                     data.acregmax = val;
  131.                 else if (!strcmp(opt, "acdirmin"))
  132.                     data.acdirmin = val;
  133.                 else if (!strcmp(opt, "acdirmax"))
  134.                     data.acdirmax = val;
  135.                 else if (!strcmp(opt, "actimeo")) {
  136.                     data.acregmin = val;
  137.                     data.acregmax = val;
  138.                     data.acdirmin = val;
  139.                     data.acdirmax = val;
  140.                 }
  141.                 else if (!strcmp(opt, "port"))
  142.                     port = val;
  143.                 else if (!strcmp(opt, "retry"))
  144.                     retry = val;
  145.                 else {
  146.                     printf("unknown nfs mount parameter: "
  147.                         "%s=%d\n", opt, val);
  148.                     goto fail;
  149.                 }
  150.             }
  151.             else {
  152.                 val = 1;
  153.                 if (!strncmp(opt, "no", 2)) {
  154.                     val = 0;
  155.                     opt += 2;
  156.                 }
  157.                 if (!strcmp(opt, "bg")) 
  158.                     bg = val;
  159.                 else if (!strcmp(opt, "fg")) 
  160.                     bg = !val;
  161.                 else if (!strcmp(opt, "soft"))
  162.                     soft = val;
  163.                 else if (!strcmp(opt, "hard"))
  164.                     soft = !val;
  165.                 else if (!strcmp(opt, "intr"))
  166.                     intr = val;
  167.                 else if (!strcmp(opt, "posix"))
  168.                     posix = val;
  169.                 else if (!strcmp(opt, "cto"))
  170.                     nocto = !val;
  171.                 else if (!strcmp(opt, "ac"))
  172.                     noac = !val;
  173.                 else {
  174.                     printf("unknown nfs mount option: "
  175.                         "%s%s\n", val ? "" : "no", opt);
  176.                     goto fail;
  177.                 }
  178.             }
  179.         }
  180.     }
  181.     data.flags = (soft ? NFS_MOUNT_SOFT : 0)
  182.         | (intr ? NFS_MOUNT_INTR : 0)
  183.         | (posix ? NFS_MOUNT_POSIX : 0)
  184.         | (nocto ? NFS_MOUNT_NOCTO : 0)
  185.         | (noac ? NFS_MOUNT_NOAC : 0);
  186.  
  187. #if 0
  188.     printf("rsize = %d, wsize = %d, timeo = %d, retrans = %d\n",
  189.         data.rsize, data.wsize, data.timeo, data.retrans);
  190.     printf("acreg (min, max) = (%d, %d), acdir (min, max) = (%d, %d)\n",
  191.         data.acregmin, data.acregmax, data.acdirmin, data.acdirmax);
  192.     printf("port = %d, bg = %d, retry = %d, flags = %.8x\n",
  193.         port, bg, retry, data.flags);
  194.     printf("soft = %d, intr = %d, posix = %d, nocto = %d, noac = %d\n",
  195.         (data.flags & NFS_MOUNT_SOFT) != 0,
  196.         (data.flags & NFS_MOUNT_INTR) != 0,
  197.         (data.flags & NFS_MOUNT_POSIX) != 0,
  198.         (data.flags & NFS_MOUNT_NOCTO) != 0,
  199.         (data.flags & NFS_MOUNT_NOAC) != 0);
  200.     goto fail;
  201. #endif
  202.  
  203.     /* create mount deamon client */
  204.  
  205.     pertry_timeout.tv_sec = 3;
  206.     pertry_timeout.tv_usec = 0;
  207.     total_timeout.tv_sec = 20;
  208.     total_timeout.tv_usec = 0;
  209.     server_addr.sin_port = 0;
  210.     msock = RPC_ANYSOCK;
  211.     if ((mclient = clntudp_create(&server_addr, MOUNTPROG, MOUNTVERS,
  212.         pertry_timeout, &msock)) == NULL) {
  213.         clnt_pcreateerror("mount clntudp_create");
  214.         goto fail;
  215.     }
  216.     mclient->cl_auth = authunix_create_default();
  217.  
  218.     /* try to mount hostname:dirname */
  219.  
  220.     clnt_stat = clnt_call(mclient, MOUNTPROC_MNT,
  221.         xdr_dirpath, &dirname,
  222.         xdr_fhstatus, &status,
  223.         total_timeout);
  224.     if (clnt_stat != RPC_SUCCESS) {
  225.         clnt_perror(mclient, "rpc mount");
  226.         goto fail;
  227.     }
  228.     if (status.fhs_status != 0) {
  229.         fprintf(stderr,
  230.             "mount: %s:%s failed, reason given by server: %s\n",
  231.             hostname, dirname, nfs_strerror(status.fhs_status));
  232.         goto fail;
  233.     }
  234.     memcpy((char *) &root_fhandle, (char *) status.fhstatus_u.fhs_fhandle,
  235.         sizeof (root_fhandle));
  236.  
  237.     /* create nfs socket for kernel */
  238.  
  239.     fsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  240.     if (fsock < 0) {
  241.         perror("nfs socket");
  242.         goto fail;
  243.     }
  244.     if (bindresvport(fsock, 0) < 0) {
  245.         perror("nfs bindresvport");
  246.         goto fail;
  247.     }
  248.     server_addr.sin_port = htons(port);
  249.     if (connect(fsock, (struct sockaddr *) &server_addr,
  250.         sizeof (server_addr)) < 0) {
  251.         perror("nfs connect");
  252.         goto fail;
  253.     }
  254.  
  255.     /* prepare data structure for kernel */
  256.  
  257.     data.version = NFS_MOUNT_VERSION;
  258.     data.fd = fsock;
  259.     memcpy((char *) &data.root, (char *) &root_fhandle,
  260.         sizeof (root_fhandle));
  261.     memcpy((char *) &data.addr, (char *) &server_addr, sizeof(data.addr));
  262.     strncpy(data.hostname, hostname, sizeof(data.hostname));
  263.  
  264.     *extra_opts = (char *) &data;
  265.  
  266.     /* clean up */
  267.  
  268.     auth_destroy(mclient->cl_auth);
  269.     clnt_destroy(mclient);
  270.     close(msock);
  271.     return 0;
  272.  
  273.     /* abort */
  274.  
  275. fail:
  276.     if (msock != -1) {
  277.         auth_destroy(mclient->cl_auth);
  278.         clnt_destroy(mclient);
  279.         close(msock);
  280.     }
  281.     if (fsock != -1)
  282.         close(fsock);
  283.     return 1;
  284. }
  285.  
  286. /*
  287.  * We need to translate between nfs status return values and
  288.  * the local errno values which may not be the same.
  289.  */
  290.  
  291. #ifndef EDQUOT
  292. #define EDQUOT    ENOSPC
  293. #endif
  294.  
  295. static struct {
  296.     enum nfs_stat stat;
  297.     int errno;
  298. } nfs_errtbl[] = {
  299.     { NFS_OK,        0        },
  300.     { NFSERR_PERM,        EPERM        },
  301.     { NFSERR_NOENT,        ENOENT        },
  302.     { NFSERR_IO,        EIO        },
  303.     { NFSERR_NXIO,        ENXIO        },
  304.     { NFSERR_ACCES,        EACCES        },
  305.     { NFSERR_EXIST,        EEXIST        },
  306.     { NFSERR_NODEV,        ENODEV        },
  307.     { NFSERR_NOTDIR,    ENOTDIR        },
  308.     { NFSERR_ISDIR,        EISDIR        },
  309.     { NFSERR_FBIG,        EFBIG        },
  310.     { NFSERR_NOSPC,        ENOSPC        },
  311.     { NFSERR_ROFS,        EROFS        },
  312.     { NFSERR_NAMETOOLONG,    ENAMETOOLONG    },
  313.     { NFSERR_NOTEMPTY,    ENOTEMPTY    },
  314.     { NFSERR_DQUOT,        EDQUOT        },
  315.     { NFSERR_STALE,        ESTALE        },
  316. #ifdef EWFLUSH
  317.     { NFSERR_WFLUSH,    EWFLUSH        },
  318. #endif
  319.     { -1,            EIO        }
  320. };
  321.  
  322. static char *nfs_strerror(int stat)
  323. {
  324.     int i;
  325.     static char buf[256];
  326.  
  327.     for (i = 0; nfs_errtbl[i].stat != -1; i++) {
  328.         if (nfs_errtbl[i].stat == stat)
  329.             return strerror(nfs_errtbl[i].errno);
  330.     }
  331.     sprintf(buf, "unknown nfs status return value: %d", stat);
  332.     return buf;
  333. }
  334.  
  335.